﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Deeper.Common;
using Deeper.DataAccess;
using System.Xml;

namespace CodeBuilder
{
	/// <summary>
	/// 数据库类型
	/// </summary>
	public enum DatabaseType
	{
		/// <summary>
		/// Sqlserver 2000 
		/// </summary>
		MSSQLSERVER = 0,
		/// <summary>
		/// Sqlserver 2005
		/// </summary>
		MSSQLSERVER2005,
		/// <summary>
		/// Oracle
		/// </summary>
		ORACLE,
		/// <summary>
		/// mysql
		/// </summary>
		MYSQL,
		/// <summary>
		/// OleDb
		/// </summary>
		OLEDB,
	}
	/// <summary>
	/// 数据库信息
	/// </summary>
	public class HDataBaseInfo
	{
		/// <summary>
		/// 数据库名
		/// </summary>
		public String DataBaseName { set; get; }
		/// <summary>
		/// 中文说明
		/// </summary>
		public string Remake { set; get; }
		/// <summary>
		/// 备注
		/// </summary>
		public string Commont { set; get; }

		public DatabaseType DatabaseType { set; get; }

		private readonly List<HTableAttribute> _tables = new List<HTableAttribute>();
		/// <summary>
		/// 表集合
		/// </summary>
		public List<HTableAttribute> Tables { get { return _tables; } }

		private readonly List<Reference> _references = new List<Reference>();
		/// <summary>
		/// 表关联
		/// </summary>
		public List<Reference> References { get { return _references; } }
	}



	public static partial class BuilderCode
	{
		private static string MakeClassName(string tbName)
		{
			int i = tbName.IndexOf("_");
			string str = tbName;
			if (i > 0)
			{
				str = tbName.Substring(i + 1, tbName.Length - i - 1);
			}
			return str;
		}

		/// <summary>
		/// 从PDM文件获取数据库信息
		/// </summary>
		/// <param name="strFileName">pmd文件名</param>
		/// <returns></returns>
		public static HDataBaseInfo LoadFromPDMXMLDocument(string strFileName)
		{
			HDataBaseInfo dbInfo = new HDataBaseInfo();


			XmlDocument doc = new XmlDocument();
			doc.Load(strFileName);
			XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
			nsm.AddNamespace("a", "attribute");
			nsm.AddNamespace("c", "collection");
			nsm.AddNamespace("o", "object");
			XmlNode rootNode = doc.SelectSingleNode("/Model/o:RootObject/c:Children/o:Model", nsm);
			if (rootNode == null)
				return null;

			dbInfo.DataBaseName = XmlHelper.ReadXMLValue(rootNode, "a:Name", nsm);
			string DBMS = XmlHelper.ReadXMLValue(rootNode, "c:DBMS/o:Shortcut/a:Code", nsm);

			///判断数据库类型
			if (DBMS.ToLower().IndexOf("oracle") > -1) dbInfo.DatabaseType = DatabaseType.ORACLE;
			else if (DBMS.ToLower().IndexOf("mssql") > -1)
				dbInfo.DatabaseType = DatabaseType.MSSQLSERVER;
			else
				dbInfo.DatabaseType = DatabaseType.OLEDB;


			dbInfo.Remake = dbInfo.DataBaseName;


			// 数据表
			foreach (XmlNode tableNode in rootNode.SelectNodes("c:Tables/o:Table", nsm))
			{
				HTableAttribute table = new HTableAttribute();
				//table.DatabaseType = dbInfo.DatabaseType;
				table.TableId = ((XmlElement)tableNode).GetAttribute("Id");
				table.TableName = XmlHelper.ReadXMLValue(tableNode, "a:Code", nsm);
				table.EntityName = MakeClassName(table.TableName);
				table.Remake = XmlHelper.ReadXMLValue(tableNode, "a:Name", nsm);
				string keyid = XmlHelper.ReadXMLValue(tableNode, "c:PrimaryKey/o:Key/@Ref", nsm);
				string comment = XmlHelper.ReadXMLValue(tableNode, "a:Comment", nsm);
				if (comment != null) table.Commont = comment;

				System.Collections.Specialized.StringCollection keys = new System.Collections.Specialized.StringCollection();
				if (keyid != null)
				{
					if (tableNode != null)
						foreach (XmlNode keyNode in tableNode.SelectNodes(string.Format("c:Keys/o:Key[@Id = '{0}']/c:Key.Columns/o:Column/@Ref", keyid), nsm))
						{
							keys.Add(keyNode.Value);
						}
				}

				if (tableNode != null)
					foreach (XmlNode fieldNode in tableNode.SelectNodes("c:Columns/o:Column", nsm))
					{
						string id = ((XmlElement)fieldNode).GetAttribute("Id");
						HColumnAttribute field = new HColumnAttribute(XmlHelper.ReadXMLValue(fieldNode, "a:Code", nsm))
													 {
														 ColumnId = id,
														 Remake = XmlHelper.ReadXMLValue(fieldNode, "a:Name", nsm),
														 SqlDataType = XmlHelper.ReadXMLValue(fieldNode, "a:DataType", nsm)
													 };


						string identity = XmlHelper.ReadXMLValue(fieldNode, "a:Identity", nsm);
						string fieldComment = XmlHelper.ReadXMLValue(tableNode, "a:Comment", nsm);
						string isnull = XmlHelper.ReadXMLValue(fieldNode, "a:Mandatory", nsm);
						string isUniquenese = XmlHelper.ReadXMLValue(fieldNode, "a:ExtendedAttributesText", nsm);

						field.Length = Convert.ToInt32(XmlHelper.ReadXMLValue(fieldNode, "a:Length", nsm));
						field.DataType = field.SqlDataType;

						if (comment != null) field.Commont = fieldComment;

						if (!isUniquenese.IsNull() && isUniquenese.Contains("Uniqueness") && isUniquenese.Contains("true")) field.IsUniqueness = true;

						field.IsNullable = true;
						if (isnull != null && isnull == "1") field.IsNullable = false;


						field.IsIdentity = false;
						if (identity != null && identity == "1") { field.IsIdentity = true; field.IsUniqueness = true; }

						if (field.SqlDataType != null)
						{
							int index = field.SqlDataType.IndexOf("(");
							if (index > 0)
								field.DataType = field.SqlDataType.Substring(0, index);
						}

						if (keys.Contains(id))
						{
							field.IsPrimary = true;
							field.IsUniqueness = true;
							table.PrimaryKey.Add(field);
						}
						table.Columns.Add(field);
					}
				dbInfo.Tables.Add(table);
			}

			#region 获取关联信息
			/*
			foreach (XmlNode refNode in rootNode.SelectNodes("c:References/o:References", nsm))
			{
				Reference reference = new Reference();
				reference.ReferenceId = ((XmlElement)refNode).GetAttribute("Id");
				reference.ReferenceCode = XmlHelper.ReadXMLValue(refNode, "a:Code", nsm);
				reference.ReferenceName = XmlHelper.ReadXMLValue(refNode, "a:Name", nsm);
				///关联模式(0..*,1..*,0..1,1..1)
				reference.Cardinality = XmlHelper.ReadXMLValue(refNode, "a:Cardinality", nsm);

				///主表
				XmlNode parentTable = refNode.SelectSingleNode("c:ParentTable/o:Table", nsm);
				reference.ParentTable = dbInfo.Tables.Find(s => s.TableId.Equals(((XmlElement)parentTable).GetAttribute("Ref")));

				XmlNode pCol = refNode.SelectSingleNode("c:Joins/c:Object1/o:Column");
				reference.ParentColumn = reference.ParentTable.Columns.Find(s => s.ColumnId.Equals(((XmlElement)pCol).GetAttribute("Ref")));

				///从表
				XmlNode childTable = refNode.SelectSingleNode("c:ChildTable/o:Table", nsm);
				reference.ChildTable = dbInfo.Tables.Find(s => s.TableId.Equals(((XmlElement)childTable).GetAttribute("Ref")));

				XmlNode cCol = refNode.SelectSingleNode("c:Joins/c:Object2/o:Column");
				reference.ChildColumn = reference.ChildTable.Columns.Find(s => s.ColumnId.Equals(((XmlElement)cCol).GetAttribute("Ref")));

				dbInfo.References.Add(reference);
			}
			 */
			#endregion

			return dbInfo;
		}




	}
}
